#include <iostream>
#include <iomanip>

#include "TFile.h"
#include "TTree.h"
#include "TH1F.h"
#include "TH2F.h"

#include "Modules.hh"

using namespace std;

ClassImp(SISScaler);
ClassImp(DgfScaler);
ClassImp(BraggChamber);

int main(int argc, char* argv[])
{
  if(argc != 3 && argc != 4)
    {
      cout<<"usage: ScalerHistograms <input file> <output file> <optional: verbose level>"<<endl;
      return 1;
    }
  
  int i,j,k;

  int VerboseLevel = 0;

  if(argc == 4)
    {
      VerboseLevel = atoi(argv[3]);
    }

  TFile* infile = new TFile(argv[1]);

  if(infile->IsZombie())
    {
      return 2;
    }

  TTree* tr = (TTree*) infile->Get("sc");

  if(tr == NULL)
    {
      cout << "could not find tree sc in file " << infile->GetName() << endl;
      return 3;
    }

  SISScaler* sisScaler = new SISScaler;
  DgfScaler* dgfScaler = new DgfScaler;
  BraggChamber* braggChamber = new BraggChamber;

  tr->SetBranchAddress("Scaler",&sisScaler);
  tr->SetBranchAddress("DgfScaler",&dgfScaler);
  tr->SetBranchAddress("BraggChamber",&braggChamber);

  TFile* outfile = new TFile(argv[2],"recreate");

  if(outfile->IsZombie())
    {
      return 4;
    }

  int NumberOfSamples = 512;

  //histograms
  //diagnostics
  TH1F* sisScalerHits = new TH1F("sisScalerHits","hit statistics of SIS scaler",96,-0.5,95.5);
  TH2F* dgfScalerHits = new TH2F("dgfScalerHits","hits statistics of DGF scaler",54,0.5,54.5,1000,0,100000);
  TH2F* dgfScalerHitsPerCluster = new TH2F("dgfScalerHitsPerCluster","hits statistics of DGF scaler per cluster",10,0.5,10.5,1000,0,100000);
  TH2F* braggTraces = new TH2F("braggTraces","Traces from bragg chamber",NumberOfSamples,0,NumberOfSamples,4096,0,4096);

  Double_t nentries = tr->GetEntries();
  Int_t nbytes = 0;
  Int_t status;

  for(i=0; i<nentries;i++) 
    {
      status = tr->GetEvent(i);
      if(status == -1)
	{
	  cerr<<"Error occured, couldn't read entry "<<i<<" from tree "<<tr->GetName()<<" in file "<<infile->GetName()<<endl;
	  return 5;
	}
      else if(status == 0)
	{
	  cerr<<"Error occured, entry "<<i<<" in tree "<<tr->GetName()<<" in file "<<infile->GetName()<<" doesn't exist"<<endl;
	  return 6;
	}
      nbytes += status;

      for(j = 0; j < braggChamber->GetNumberOfSubEvents(); j++)
	{
	  BraggChamberSubEvent* subevent = braggChamber->GetSubEvent(j);

	  if(VerboseLevel > 2)
	    {
	      cout<<"got subevent "<<j<<endl;
	    }
	  vector<unsigned int>* data = subevent->GetChannel(0);

	  if(VerboseLevel > 2)
	    {
	      cout<<"got channel 0"<<endl;
	    }

	  for(k = 0; k < data->size(); k++)
	    {
	      if(k >= NumberOfSamples)
		{
		  cerr<<"supposed to have only "<<NumberOfSamples<<" samples, but data is "<<data->size()<<" samples long"<<endl;
		  break;
		}
	      braggTraces->Fill((Axis_t) k, (Axis_t) (*data)[k]);

	      if(VerboseLevel > 3)
		{
		  cout<<"filled "<<k<<endl;
		}
	    }

	  if(VerboseLevel > 2)
	    {
	      cout<<"done with "<<data->size()<<" samples"<<endl;
	    }
	}

      if(VerboseLevel > 1)
	{
	  cout<<"done with "<<braggChamber->GetNumberOfSubEvents()<<" subevents"<<endl;
	}

      for(j = 0; j < sisScaler->GetNumberOfSubEvents(); j++)
	{
	  ScalerSubEvent* subevent = sisScaler->GetSubEvent(j);

	  if(VerboseLevel > 2)
	    {
	      cout<<"got subevent "<<j<<endl;
	    }

	  for(k = 0; k < subevent->Size(); k++)
	    {
	      sisScalerHits->SetBinContent(subevent->GetChannel(k),subevent->GetValue(k));

	      if(VerboseLevel > 3)
		{
		  cout<<"filled "<<k<<endl;
		}
	    }

	  if(VerboseLevel > 2)
	    {
	      cout<<"done with "<<subevent->Size()<<" samples"<<endl;
	    }
	}

      if(VerboseLevel > 1)
	{
	  cout<<"done with "<<sisScaler->GetNumberOfSubEvents()<<" subevents"<<endl;
	}

      for(j = 0; j < dgfScaler->GetNumberOfSubEvents(); j++)
	{
	  DgfScalerSubEvent* subevent = dgfScaler->GetSubEvent(j);

	  if(VerboseLevel > 2)
	    {
	      cout<<"got subevent "<<j<<endl;
	    }

	  dgfScalerHits->Fill((Axis_t) subevent->ModuleNumber(), (Axis_t) subevent->NumberOfEvents());
	  dgfScalerHitsPerCluster->Fill((Axis_t) subevent->ClusterID(), (Axis_t) subevent->NumberOfEvents());
	}

      if(VerboseLevel > 1)
	{
	  cout<<"done with "<<dgfScaler->GetNumberOfSubEvents()<<" subevents"<<endl;
	}

      if(i%1000 == 0)
	{
	  cout<<setw(5)<<setiosflags(ios::fixed)<<setprecision(1)<<(100.*i)/nentries<<" % done\r"<<flush;
	}
    }

  sisScalerHits->Write("",TObject::kOverwrite);
  dgfScalerHits->Write("",TObject::kOverwrite);
  dgfScalerHitsPerCluster->Write("",TObject::kOverwrite);
  braggTraces->Write("",TObject::kOverwrite);

  infile->Close();
  outfile->Close();

  return 0;
}
